package users

import (
	"context"
	"errors"
	"github.com/golang-jwt/jwt/v5"
	"product/common/datetime"
	"product/common/encryption"
	"product/common/jwts"
	"product/common/validator"
	"strconv"
	"time"

	"product/authorization/serve/internal/svc"
	"product/authorization/serve/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type LoginUsersLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// NewLoginUsersLogic Login users
func NewLoginUsersLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginUsersLogic {
	return &LoginUsersLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *LoginUsersLogic) LoginUsers(req *types.LoginUserReq) (resp *types.LoginUserResp, err error) {
	ok, err := validLoginInput(req)
	if !ok && err != nil {
		return &types.LoginUserResp{
			ID:    "",
			Token: "",
		}, nil
	}

	// 获取用户盐值
	salt, err := l.svcCtx.UsersModel.FindSalt(l.ctx, req.UserName)
	if err != nil || validator.IsEmptyString(salt) {
		return &types.LoginUserResp{
			ID:    "",
			Token: "",
		}, nil
	}

	pass := genLoginInputPwd(salt, req.PassWord)
	user, err := l.svcCtx.UsersModel.CheckValidUser(l.ctx, req.UserName, pass)
	if err != nil {
		return &types.LoginUserResp{
			ID:    "",
			Token: "",
		}, nil
	}
	// TODO: 生成token
	jwtTime := time.Now()
	// 签发者
	claims := &jwts.JwtHollyClaims{
		ID:   user.ID,
		Name: user.UserName,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(datetime.AddHours(jwtTime, l.svcCtx.Config.JwtConf.Expires)),
			IssuedAt:  jwt.NewNumericDate(jwtTime),
			Issuer:    l.svcCtx.Config.JwtConf.Issuer,
			Subject:   "Token",
		},
	}

	token, err := jwts.GenToken(claims, l.svcCtx.Config.JwtConf.Secret)
	if err != nil || validator.IsEmptyString(token) {
		return &types.LoginUserResp{
			ID:    "",
			Token: "",
		}, nil
	}
	return &types.LoginUserResp{
		ID:    strconv.FormatInt(user.ID, 10),
		Token: token,
	}, nil

}

// 验证输入
func validLoginInput(input *types.LoginUserReq) (bool, error) {
	if validator.IsEmptyString(input.UserName) {
		return false, errors.New("用户名不能为空")
	}
	return true, nil
}

// 生成密码
func genLoginInputPwd(slat, inputPwd string) string {
	return encryption.Md5WithSalt(inputPwd, slat)
}
